package com.learnaop.javaaop.example.aop.aspectj;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MyAspectJ01 {
    @Pointcut("execution(* com.learnaop.javaaop.example.aop.service01.*.*(..))")
    public void executionPointcut() {
        // execution指定那些路径下的那些方法可以执行该切片
    }

    @Pointcut("within(com.learnaop.javaaop.example.aop.service01.impl01.AopUsedService01Impl)")
    public void withinPointcut() {
        // within指定那些类下的那些方法可以执行该切片
    }

//
//    @Pointcut("this(com.learnaop.javaaop.example.aop.service.impl02.AopUsedService02Impl)")
//    public void thisPointcut() {
//        // this只能指定代理对象的类型下的那些方法可以执行该切片，若目标类没有代理类接口会报错 -- 默认JDK代理
//        // 可通过JavaAopConfig.class 下的 @EnableAspectJAutoProxy(proxyTargetClass = true) 解决 -- cglib代理
//    }
//

    @Pointcut("target(com.learnaop.javaaop.example.aop.service01.impl01.AopUsedService01Impl)")
    public void targetPointcut() {
        // target指定目标对象的类型下的那些方法可以执行该切片
    }

    @Pointcut("args(String)")
    public void argsPointcut() {
        // args指定符合特定参数对象的方法可以执行该切片
    }
//
//    @Pointcut("@args(com.learnaop.javaaop.example.aop.annotation.Anno01)")
//    public void argsForAnnotationPointcut() {
//        //
//    }
//
//    @Pointcut("@within(com.learnaop.javaaop.example.aop.annotation.Anno01)")
//    public void withinForAnnotationPointcut() {
//        //
//    }
//
//    @Pointcut("@annotation(com.learnaop.javaaop.example.aop.annotation.Anno01)")
//    public void annotationForAnnotationPointcut() {
//        //
//    }

    @Before("executionPointcut()")
    public void beforeForAnnotation() {
        System.out.println("@Before because of the path that tag by label 'execution', I execute ... ");
    }

    @AfterReturning(value = "withinPointcut()", returning = "res")
    public void method02(Object res) {
        System.out.println("@AfterReturning because of the path that tag by label 'within', I executed ... res is " + res);
    }

    @Around("targetPointcut()")
    public void beforeMethodWithTargetClass(ProceedingJoinPoint proceedingJoinPoint) {
        System.out.println("@Around before get params because of the path that tag by label 'target', I executed ... ");
        try {
            proceedingJoinPoint.getArgs();
            proceedingJoinPoint.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        System.out.println("@Around after used method because of the path that tag by label 'target', I executed ... ");
    }

    @AfterThrowing(value = "executionPointcut()", throwing = "exception")
    public void beforeMethodWithTargetPath(Exception exception) {
        System.out.println("@AfterThrowing because of the path that tag by label 'execution', I execute ... exception is " + exception);
    }

    @After("argsPointcut() && withinPointcut()")
    public void method01() {
        System.out.println("@After because of the path that tag by label 'args', I executed ... ");
    }
//
//    @After("argsPointcut()")
//    public void method03() {
//        System.out.println("@After because of the path that tag by label 'args', I executed ... ");
//    }
}
